use std::os::windows::process::CommandExt;

#[tauri::command]
async fn execute_command(
    command: String,
    args: Vec<String>,
    cwd: Option<String>,
    encoding: Option<String>,
) -> Result<String, String> {
    let output = tokio::task::spawn_blocking(move || {
        let mut cmd = std::process::Command::new(command);
        cmd.args(&args)
            .creation_flags(0x08000000)
            .stdout(std::process::Stdio::piped())
            .stderr(std::process::Stdio::piped());
        if let Some(cwd) = cwd {
            cmd.current_dir(cwd);
        }

        let output = cmd.output().map_err(|e| e.to_string())?;

        match encoding.as_deref() {
            Some("gbk") => {
                let decoder = encoding_rs::GBK;
                let (stdout, _, _) = decoder.decode(&output.stdout);
                let (stderr, _, _) = decoder.decode(&output.stderr);
                if output.status.success() {
                    Ok(stdout.into_owned())
                } else {
                    Err(stderr.into_owned())
                }
            }
            Some("utf-8") => {
                if output.status.success() {
                    Ok(String::from_utf8_lossy(&output.stdout).into_owned())
                } else {
                    Err(String::from_utf8_lossy(&output.stderr).into_owned())
                }
            }
            _ => Err(String::from("Unsupported encoding")),
        }
    })
    .await
    .map_err(|e| e.to_string())??;
    Ok(output)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    #[cfg(debug_assertions)] // 尽可能提前初始化
    let devtools = tauri_plugin_devtools::init();

    let mut builder = tauri::Builder::default();

    #[cfg(debug_assertions)]
    {
        builder = builder.plugin(devtools);
    }

    #[cfg(not(debug_assertions))]
    {
        builder = builder
            .plugin(tauri_plugin_prevent_default::init())
    }

    builder.plugin(tauri_plugin_store::Builder::new().build())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_opener::init())
        .plugin(tauri_plugin_fs::init())
        .invoke_handler(tauri::generate_handler![execute_command])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
